package com.sd365.permission.centre.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sd365.common.core.annotation.stuffer.CommonFieldStuffer;
import com.sd365.common.core.annotation.stuffer.IdGenerator;
import com.sd365.common.core.annotation.stuffer.MethodTypeEnum;
import com.sd365.common.core.common.aop.MyPageInfo;
import com.sd365.common.core.common.exception.BusinessException;
import com.sd365.common.core.common.exception.code.BusinessErrorCode;
import com.sd365.common.core.context.BaseContextHolder;
import com.sd365.common.core.mq.ActionType;
import com.sd365.common.util.BeanException;
import com.sd365.permission.centre.dao.mapper.*;
import com.sd365.permission.centre.entity.*;
import com.sd365.permission.centre.pojo.dto.*;
import com.sd365.permission.centre.pojo.dto.pcp.PcpUserDTO;
import com.sd365.permission.centre.pojo.dto.shop.ShopBuyerDTO;
import com.sd365.permission.centre.pojo.query.UserQuery;
import com.sd365.permission.centre.service.UserService;
import com.sd365.permission.centre.service.exception.UserCentreExceptionCode;
import com.sd365.permission.centre.service.util.SendMQMessageUtil;
import com.sd365.common.util.BeanUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import tk.mybatis.mapper.entity.Example;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


import static java.util.stream.Collectors.toList;

@Service
public class UserServiceImpl extends AbstractBaseDataServiceImpl implements UserService {
    @Autowired
    private SendMQMessageUtil sendMQMessageUtil;
    private static final String TABLE_NAME = "user";
    @Autowired
    private IdGenerator idGenerator;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private DepartmentMapper departmentMapper;
    @Autowired
    private PositionMapper positionMapper;
    @Autowired
    private CompanyMapper companyMapper;
    @Autowired
    private OrganizationMapper organizationMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private TenantMapper tenantMapper;
    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.ADD)
    public Boolean add(@Valid UserDTO userDTO) {
        try{
            User user = BeanUtil.copy(userDTO,User.class);
            List<Role>roles = BeanUtil.copyList(userDTO.getRoleList(),Role.class);
            user.setRoleList(roles);
            if (userMapper.selectUserByCode(userDTO.getCode())>0){
//                throw new Exception("用户工号不能重复");
                return false;
            }
            user.setId(idGenerator.snowflakeId());
            user.setVersion(1L);
            Boolean flag1 = userMapper.insert(user) > 0;
            if (flag1) {
                sendMQMessageUtil.SendMessage(ActionType.INSERT,SendMQMessageUtil.EXCHANGE_NAME,TABLE_NAME,user);
            }
            List<Role> roleList = user.getRoleList();
            for (Role role : roleList) {
                UserRole userRole = new UserRole(user.getId(),role.getId());
                super.baseDataStuff4Add(userRole);
                userRole.setId(idGenerator.snowflakeId());
                userRole.setUserId(user.getId());
                userRole.setRoleId(role.getId());
                userRole.setCompanyId(user.getCompanyId());
                userRole.setOrgId(user.getOrgId());
                userRole.setTenantId(user.getTenantId());
                userRole.setVersion(1L);
                int result = userRoleMapper.insert(userRole);
                if (result <=0 ){
                    throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATA_USER_DB_EXCEPTION_CODE,new Exception("用户角色分配失败"));
                }
            }
            return flag1;
        }catch (BeanException ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATA_USER_DB_EXCEPTION_CODE, ex);
        } catch (Exception ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATA_USER_DB_EXCEPTION_CODE, ex);
        }

    }

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.DELETE)
    public Boolean remove(Long id, Long version) {
        try {
            Example example = new Example(User.class);
            example.createCriteria().andEqualTo("id", id).andEqualTo("version", version);

            Boolean flag = userMapper.deleteByExample(example) > 0;
            if (flag) {
                User user = new User();
                user.setId(id);
                user.setVersion(version);
                sendMQMessageUtil.SendMessage(ActionType.DELETE, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, user);
            }
            userRoleMapper.deleteAllByUserID(id);
            return flag;
        } catch (Exception e) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_COMPANY_REMOVE_EXCEPTION_CODE, e);
        }
    }

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.UPDATE)
    public Boolean modify(UserDTO userDTO) {
        try{
            User user = BeanUtil.copy(userDTO, User.class);
            super.baseDataStuff4Updated(user);
            Example example = new Example(User.class);
            example.createCriteria().andEqualTo("id", userDTO.getId()).andEqualTo("version", userDTO.getVersion());
            user.setUpdatedTime(new Date());
            Boolean flag = userMapper.updateByExampleSelective(user, example) > 0;
            if (flag) {
                sendMQMessageUtil.SendMessage(ActionType.UPDATE, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, user);
            }
            userRoleMapper.deleteAllByUserID(user.getId());
            List<Role> roleList = user.getRoleList();
            for (Role role : roleList){
                UserRole userRole = new UserRole(user.getId(),role.getId());
                super.baseDataStuff4Add(userRole);
                userRole.setId(idGenerator.snowflakeId());
                userRole.setUserId(user.getId());
                userRole.setRoleId(role.getId());
                userRole.setCompanyId(user.getCompanyId());
                userRole.setOrgId(user.getOrgId());
                userRole.setTenantId(user.getTenantId());
                userRole.setVersion(1L);
                int result = userRoleMapper.insert(userRole);
                if (result <=0 ){
                    throw new BusinessException(UserCentreExceptionCode.RESOURCE_ASSIGN_FAILED,new Exception("用户角色分配失败"));
                }
            }
            return flag;
        }catch (BeanException ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATA_USER_DB_EXCEPTION_CODE, ex);
        } catch (Exception ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_BASEDATA_USER_DB_EXCEPTION_CODE, ex);
        }

    }


    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.UPDATE)
    public Boolean modifyWithNewRole(UserDTO[] userDTOS) {
        if (userDTOS.length == 0){
            throw new BusinessException(BusinessErrorCode.SYSTEM_SERVICE_ARGUMENT_NOT_VALID, new Exception("modifyWithNewRole 方法错误"));
        }
        for (UserDTO userDTO : userDTOS){
            User user = BeanUtil.copy(userDTO, User.class);
//            super.baseDataStuff4Updated(user);
            Long userId = userDTO.getId();
            userRoleMapper.deleteAllByUserID(userId);
            List<Role> roleList = BeanUtil.copyList(userDTO.getRoleList(),Role.class);
            for (Role role : roleList){
                UserRole userRole = new UserRole(user.getId(),role.getId());
                super.baseDataStuff4Add(userRole);
                userRole.setId(idGenerator.snowflakeId());
                userRole.setUserId(userId);
                userRole.setRoleId(role.getId());
                userRole.setCompanyId(user.getCompanyId());
                userRole.setOrgId(user.getOrgId());
                userRole.setTenantId(user.getTenantId());
                userRole.setVersion(1L);
                int result = userRoleMapper.insert(userRole);
                if (result <=0 ){
                    throw new BusinessException(UserCentreExceptionCode.RESOURCE_ASSIGN_FAILED,new Exception("用户角色分配失败"));
                }
            }
//            Example example = new Example(User.class);
//            example.createCriteria().andEqualTo("id", userDTO.getId()).andEqualTo("version", userDTO.getVersion());
//            user.setUpdatedTime(new Date());
//            Boolean flag = userMapper.updateByExampleSelective(user, example) > 0;
//            if (flag) {
//                sendMQMessageUtil.SendMessage(ActionType.UPDATE, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, user);
//                continue;
//            }else {
//                throw new BusinessException(UserCentreExceptionCode.RESOURCE_ASSIGN_FAILED,new Exception("用户角色分配失败"));
//            }
        }
        return true;
    }

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.QUERY)
    public List<User> commonQuery(UserQuery userQuery) {
        if (userQuery == null) {
            throw new BusinessException(BusinessErrorCode.SYSTEM_SERVICE_ARGUMENT_NOT_VALID, new Exception("commonQueryUser 方法错误"));
        }
        try {
            User user = BeanUtil.copy(userQuery, User.class);
            List<User> users = new ArrayList<>();
            if (userQuery.getRoleId() != null) {
                List<UserRole> userRoleList = userRoleMapper.selectByRoleId(userQuery.getRoleId());
                for (UserRole userRole : userRoleList) {
                    users.add(userMapper.selectById(userRole.getUserId()));
                }
                for (User temp2 : users){
                    temp2.setRoleList(roleMapper.selectRoleByUserid(temp2.getId()));
                }
            }
            //PageHelper.startPage(userQuery.getPageNum(), userQuery.getPageSize());
            List<User> userList = userMapper.commonQuery(user);
            for (User temp1 : userList){
                temp1.setRoleList(roleMapper.selectRoleByUserid(temp1.getId()));
            }
            //Page page = (Page) userList;
            //BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo(page.getTotal(), page.getPages())));
            if (!users.isEmpty()){
                List<User> result = users.stream().filter(item -> userList.contains(item)).collect(toList());
                List<User> res = result.stream().skip((userQuery.getPageNum()-1)*userQuery.getPageSize()).limit(userQuery.getPageSize()).collect(toList());

                BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo((long) result.size(), result.size() / userQuery.getPageSize() + (result.size() % userQuery.getPageSize() == 0 ? 0 : 1))));
                return res;
            }
            List<User> res = userList.stream().skip((userQuery.getPageNum()-1)*userQuery.getPageSize()).limit(userQuery.getPageSize()).collect(toList());

            BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo((long) userList.size(), userList.size() / userQuery.getPageSize() + (userList.size() % userQuery.getPageSize() == 0 ? 0 : 1))));
            return res;
        } catch (BeanException ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_COMPANY_COMMONQUERY_EXCEPTION_CODE, ex);
        } catch (Exception ex) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_COMPANY_COMMONQUERY_EXCEPTION_CODE, ex);
        }
    }
//        String name = userQuery.getName();
//        String code = userQuery.getCode();
//        String tel = userQuery.getTel();
//        Long roleId = userQuery.getRoleId();
//        Long departmentId = userQuery.getDepartmentId();
//        Long positionId = userQuery.getPositionId();
//        Long orgId = userQuery.getOrgId();
//        Long companyId = userQuery.getCompanyId();
//
//        User user = new User();
//        user.setName(name);
//        user.setCode(code);
//        user.setTel(tel);
//        user.setDepartment(departmentMapper.selectById(departmentId));
//        user.setPosition(positionMapper.selectPositionById(positionId));
//        user.setCompany(companyMapper.selectById(companyId));
//
//        user.setOrganization(organizationMapper.selectById(orgId));
//
//        if (roleId == null){
//            try {
//                List<User> userList = userMapper.commonQuery(user);
//                Page page = (Page) userList;
//                BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo(page.getTotal(), page.getPages())));
//                return userList;
//            } catch (Exception e) {
//                throw new BusinessException(UserCentreExceptionCode.BUSINESS_COMPANY_COMMONQUERY_EXCEPTION_CODE, e);
//            }
//        }else{
//            try {
//                List<User> userList = userMapper.commonByQueryRoleId(user,roleId);
//                Page page = (Page) userList;
//                BaseContextHolder.set("pageInfo",JSON.toJSONString(new MyPageInfo(page.getTotal(),page.getPages())));
//                return userList;
//            }catch (Exception e){
//                throw new BusinessException(UserCentreExceptionCode.BUSINESS_COMPANY_COMMONQUERY_EXCEPTION_CODE, e);
//            }
//        }


    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.QUERY)
    public User queryById(Long id) {
        User user = userMapper.selectById(id);
        user.setOrganization(organizationMapper.selectById(user.getOrgId()));
        user.setPosition(positionMapper.selectPositionById(user.getPositionId()));
        user.setCompany(companyMapper.selectById(user.getCompanyId()));
        user.setDepartment(departmentMapper.selectById(user.getDepartmentId()));
        user.setRoleList(roleMapper.selectRoleByUserid(id));
        return user;
    }

    @Override
    public List<Role> queryAllRole() {
        List<Role> roleList = roleMapper.selectAll();
        return roleList;
    }

    @Override
    public List<Department> queryAllDepartment() {
        List<Department> departmentList = departmentMapper.selectAll();
        return departmentList;
    }

    @Override
    public List<Position> queryAllPosition() {
        List<Position> positionList = positionMapper.selectAll();
        return positionList;
    }

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.UPDATE)
    public Boolean batchUpdate(UserDTO[] userDTOS) {
        if (userDTOS.length == 0){
            throw new BusinessException(BusinessErrorCode.SYSTEM_SERVICE_ARGUMENT_NOT_VALID, new Exception("batchUpdate 方法错误"));
        }
        Assert.notEmpty(userDTOS, "批量更新参数不可以为空");
        for (UserDTO userDTO : userDTOS){
            User user = BeanUtil.copy(userDTO, User.class);
            baseDataStuff4Updated(userDTO);
            Example example = new Example(User.class);
            example.createCriteria().andEqualTo("id", userDTO.getId()).andEqualTo("version", userDTO.getVersion());
            super.baseDataStuff4Updated(user);
            int result = userMapper.updateByExampleSelective(user, example);
            if (result <= 0){
                throw new BusinessException(BusinessErrorCode.SYSTEM_SERVICE_OTHER_EXCEPTION, new Exception(String.format("更新的记录id %d 没有匹配到版本", userDTO.getId())));
            }else{
                sendMQMessageUtil.SendMessage(ActionType.UPDATE, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, user);
            }
        }
        return true;
    }

    @Override
    @CommonFieldStuffer(methodType = MethodTypeEnum.DELETE)
    public Boolean batchDelete(UserDTO[] userDTOS) {
        if (userDTOS.length == 0) {
            throw new BusinessException(BusinessErrorCode.SYSTEM_SERVICE_ARGUMENT_NOT_VALID, new Exception("batchDelete 方法错误"));
        }
        Assert.notEmpty(userDTOS, "批量删除参数不可以为空");
        for (UserDTO userDTO : userDTOS) {
            Example example = new Example(User.class);
            example.createCriteria().andEqualTo("id", userDTO.getId());
            int result = userMapper.deleteByExample(example);
            if (result <= 0) {
                throw new BusinessException(BusinessErrorCode.SYSTEM_SERVICE_OTHER_EXCEPTION, new Exception(String.format("删除的记录id %d 没有匹配到版本", userDTO.getId())));
            }else {
                User user = new User();
                user.setId(userDTO.getId());
                user.setVersion(userDTO.getVersion());
                sendMQMessageUtil.SendMessage(ActionType.DELETE, SendMQMessageUtil.EXCHANGE_NAME, TABLE_NAME, user);
            }
        }
        return true;
    }



    /**
     * TODO
     * TODO
     * @return
     */
    @Override
    public Boolean firstStartMd5() {
        return null;
    }

    /**
     * TODO
     * @param pcpUserDTOS
     * @return
     */
    @Override
    public Boolean pcpUserRegister(List<PcpUserDTO> pcpUserDTOS) {
        return null;
    }

    /**
     * TODO
     * @param pcpUserDTOS
     * @return
     */
    @Override
    public Boolean pcpUserUpdate(List<PcpUserDTO> pcpUserDTOS) {
        return null;
    }

    /**
     * TODO
     * @param pcpUserDTOS
     * @return
     */
    @Override
    public Boolean updateUserLockStatus(List<PcpUserDTO> pcpUserDTOS) {
        if (pcpUserDTOS.size() == 0) {
            throw new BusinessException(BusinessErrorCode.SYSTEM_SERVICE_ARGUMENT_NOT_VALID, new Exception("updateUserLockStatus 方法错误"));
        }
        for (PcpUserDTO pcpUserDTO:pcpUserDTOS){
            User user = BeanUtil.copy(pcpUserDTO,User.class);
            // todo 查询用户
            user.setStatus((byte) 2);
            Long version = user.getVersion();
            user.setVersion(version++);
            int result = userMapper.updateStatus(user);
            if (result <= 0){
                throw new BusinessException(BusinessErrorCode.SYSTEM_SERVICE_OTHER_EXCEPTION, new Exception(String.format("锁定的记录id %d 没有匹配到版本", user.getId())));
            }
        }
        return true;
    }

    /**
     * TODO
     * @param shopBuyerDTOS
     * @return
     */
    @Override
    public Boolean shopUserRegister(List<ShopBuyerDTO> shopBuyerDTOS) {
        return null;
    }

    @Override
    public Boolean updatePassword(UserDTO userDTO) {
        String code = userDTO.getCode();
        String password = userDTO.getPassword();
        User user = getUser(code);
        user.setPassword(password);
        Boolean flag = userMapper.update(user) > 0;
        if (flag){
            sendMQMessageUtil.SendMessage(ActionType.UPDATE,SendMQMessageUtil.EXCHANGE_NAME,TABLE_NAME,user);
        }
        return flag;
    }

    @Override
    public User getUser(String code) {
        User user = userMapper.selectByCode(code);
        return user;
    }
}
